﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Models;
using DAL;
using System.Net.Sockets;
using System.Windows.Forms;
using MySocketHelper;
using System.Threading;
namespace BLL
{
    /// <summary>
    /// 交通管制访问类
    /// </summary>
    public class TrafficManager
    {
        private TrafficInfoService objTrafficInfoService = new TrafficInfoService();
        private AGVCommunicationManager objAGVCommunicationManager = new AGVCommunicationManager();
        /// <summary>
        /// 获取所有交通管制的配置
        /// </summary>
        /// <returns></returns>
        public List<TrafficInfo> GetAlltrafficInfo()
        {
            return objTrafficInfoService.GetAlltrafficInfo();
        }
        /// <summary>
        /// 按条件组合查询交管信息
        /// </summary>
        /// <param name="landNum">地标号</param>
        /// <param name="cmdName">命令名称</param>
        /// <param name="area">区域号</param>
        /// <returns></returns>
        public List<TrafficInfo> QueryTrafficInfo(string landNum, string cmdName, string area)
        {
            if (Convert.ToInt32(landNum) == 0) landNum = "";
            if (Convert.ToInt32(area) == 0) area = "";
            if (cmdName == "空") cmdName = "";
            return objTrafficInfoService.QueryTrafficInfo(landNum,cmdName,area);
        }
        /// <summary>
        /// 用过地标号获取所有对应的交管功能
        /// </summary>
        /// <param name="landNum">地标号</param>
        /// <returns>交通功能集合</returns>
        public List<TrafficInfo> GettrafficInfoByLandNum(string landNum)
        {
            return objTrafficInfoService.GettrafficInfoByLandNum(landNum);
        }
        /// <summary>
        /// 用过地标号获取所有对应的交管功能
        /// </summary>
        /// <param name="landNum">地标号</param>
        /// <param name="listTraffic">所有交管指令集合</param>
        /// <returns>该地标号所有指令集合</returns>
        public List<TrafficInfo> GettrafficInfoByLandNum(int landNum,List<TrafficInfo> listTraffic)
        {
            return listTraffic.FindAll(s => s.LandNum == landNum);
        }
        #region 增删改
        public int AddTrafficInfo(TrafficInfo objTraffic)
        {
            if (objTrafficInfoService.IsExitsTraffic(objTraffic.LandNum.ToString(), objTraffic.CMD.ToString(),objTraffic.Area.ToString()) >= 1)
            {
                throw new Exception("该指令已经存在，不能重复输入");
            }
            return objTrafficInfoService.AddTrafficInfo(objTraffic);
        }
        public int ModifyTrafficInfo(TrafficInfo objTraffic)
        {
            return objTrafficInfoService.ModifyTrafficInfo(objTraffic);
        }
        public int DeleteTrafficInfo(string id)
        {
            return objTrafficInfoService.DeleteTrafficInfo(id);
        }
        #endregion

        #region 交通管制算法1
       /// <summary>
        /// 交通管制算法
       /// </summary>
       /// <param name="listTraffic">当前所有被交管信息列表</param>
       /// <param name="objAGV">当前AGV状态</param>
       /// <param name="dic">所有AGVSocket信息</param>
       /// <param name="listAllTraffic">所有配置好交管指令集</param>       
        public void TrafficControl(List<TrafficInfo> listTraffic, AGVInfo objAGV, Dictionary<string, Socket> dic, List<TrafficInfo> listAllTraffic, DataGridView dgvTrafficView)
        {
            try
            {
                //【1】根据地标查找功能
                List<TrafficInfo> list = new List<TrafficInfo>();
                if (objAGV.PreLandNum != 0)
                    list = GettrafficInfoByLandNum(objAGV.PreLandNum, listAllTraffic);
               // list = GettrafficInfoByLandNum(objAGV.PreLandNum.ToString());
                //【2】判断该地标是否存在交管功能（启动或释放交管）
                if (list.Count > 0)
                {              
                    //【3】交管区信息赋值
                    for (int i = 0; i < list.Count; i++)
                    {

                        /*--------------------------------------------启动交管指令--------------------------------------------*/
                        if (list[i].CMD == 0)
                        {
                            //寻找该区域的交管是否已经存在，存在则管制该AGV(需要增加一个状态：是否已被管制主，如果都被管制主，则一直通过交管区域。有没有没管制主，则被管制)
                            List<TrafficInfo> listInTraffic = listTraffic.FindAll(s => s.Area == list[i].Area && s.IP != objAGV.IP);
                            //先判断该区域是否已存在，避免重复添加
                            List<TrafficInfo> listHaveTraffic = listTraffic.FindAll(s => s.Area == list[i].Area && s.IP == objAGV.IP);
                            //里面已经存在交管AGV&&该AGV不存在，才能进入；避免多次进入
                            if (listInTraffic.Count >= 1 && listHaveTraffic.Count == 0)
                            {
                                    //发送停止信号
                                    OrderList objOrderList = new OrderList() { CMD = 0x14 };
                                    objAGVCommunicationManager.SendDataByIP(objAGV.IP, dic, objOrderList);//发送数据
                            }                                   
                            if(listHaveTraffic.Count == 0 && objAGV != null)
                            {
                                lock (objAGV)
                                {
                                    listTraffic.Add(new TrafficInfo
                                    {
                                        IP = objAGV.IP,
                                        AGVName = objAGV.AGVName,
                                        InTraffic = DateTime.Now,
                                        TrafficStatus = listInTraffic.Count == 0 ? "通行中" : "管制中",
                                        Area = list[i].Area
                                    }); //新增一个进入交管区域的AGV
                                }                                        
                            }
                        }
                        /*--------------------------------------------释放交管指令--------------------------------------------*/
                        else if (list[i].CMD == 1)
                        {
                            // list[i].OutTraffic = DateTime.Now;
                            //查找对应区域和交管AGV，并清除该AGV在交管区域的信息（释放交管）
                            int index = listTraffic.FindIndex(s => s.Area == list[i].Area && s.IP == objAGV.IP);
                            //释放被管制的AGV,不能寻找自己
                            List<TrafficInfo> listOutTraffic = listTraffic.FindAll(s => s.Area == list[i].Area && s.IP != objAGV.IP);
                            //找到有被管制的AGV，如果多个释放最前一台
                            if (listOutTraffic.Count >= 1 && index != -1)
                            {
                                //发送释放信号
                                Thread.Sleep(200); //延时200ms再发释放，以防AGV不释放
                                OrderList objOrderList = new OrderList() { CMD = 0x15 };
                                objAGVCommunicationManager.SendDataByIP(listOutTraffic[0].IP, dic, objOrderList);//发送数据 释放最前面一台
                                int outIndex = listTraffic.FindIndex(s => s.Area == list[i].Area && s.IP == listOutTraffic[0].IP);
                                if (outIndex != -1) listTraffic[outIndex].TrafficStatus = "通行中";
                            }
                            lock (listTraffic)
                            {
                                if (index != -1)
                                    listTraffic.RemoveAt(index); //删除当前运行出交管区域的AGV信息
                            }                                  
                        }
                    }
                }
                listTraffic.Sort(new AreaASC()); //按区域排序
                //dgvTrafficView.Invoke(new Action<List<TrafficInfo>>(s =>
                //{
                //    dgvTrafficView.AutoGenerateColumns = false; dgvTrafficView.DataSource = null; dgvTrafficView.DataSource = s;
                //}), listTraffic);
            }
            catch (Exception ex)
            {
                
                throw new Exception("交管异常！异常信息："+ex.Message);
            }
            
        }
        #endregion

        #region 交通管制算法2
        /// <summary>
        /// 交通管制算法
        /// </summary>
        /// <param name="listTraffic">当前所有被交管信息列表</param>
        /// <param name="objAGV">当前AGV状态</param>
        /// <param name="dic">所有AGVSocket信息</param>
        /// <param name="listAllTraffic">所有配置好交管指令集</param>       
        public void TrafficControl(List<TrafficInfo> listTraffic, DataGridView dgvAGV, Dictionary<string, Socket> dic, List<TrafficInfo> listAllTraffic, DataGridView dgvTrafficView)
        {
            try
            {
                DataGridView objDgvAGV = dgvAGV;
                for (int j = 0; j < objDgvAGV.Rows.Count; j++)
                {
                    int PreLandNum = Convert.ToInt32(objDgvAGV.Rows[j].Cells["PreLandNum"].Value);
                    string IP = objDgvAGV.Rows[j].Cells["IP"].Value.ToString();
                    string AGVName = objDgvAGV.Rows[j].Cells["AGVName"].Value.ToString();
                    string PreAGVStatus = objDgvAGV.Rows[j].Cells["PreAGVStatus"].Value.ToString();
                    string OnLineStatus = objDgvAGV.Rows[j].Cells["OnLineStatus"].Value.ToString();
                    //封装AGV当前信息
                    //AGVInfo objAGV = new AGVInfo()
                    //{
                    //    AGVName = objDgvAGV.Rows[j].Cells["AGVName"].Value.ToString(),
                    //    IP = objDgvAGV.Rows[j].Cells["IP"].Value.ToString(),
                    //    PreLandNum = Convert.ToInt32(objDgvAGV.Rows[j].Cells["PreLandNum"].Value),
                    //    PreAGVStatus = objDgvAGV.Rows[j].Cells["PreAGVStatus"].Value.ToString(),
                    //    OnLineStatus = objDgvAGV.Rows[j].Cells["OnLineStatus"].Value.ToString(),
                    //};
                    if (OnLineStatus != "离线" && PreAGVStatus !="失联")
                    {
                        //【1】根据地标查找功能
                        List<TrafficInfo> list = new List<TrafficInfo>();
                        //if (PreLandNum != 0)
                        //list = GettrafficInfoByLandNum(PreLandNum, listAllTraffic);
                        if (PreLandNum != 0)
                            list = GettrafficInfoByLandNum(PreLandNum.ToString());
                        //【2】判断该地标是否存在交管功能（启动或释放交管）
                        if (list.Count > 0)
                        {
                            //【3】交管区信息赋值
                            for (int i = 0; i < list.Count; i++)
                            {

                                /*--------------------------------------------启动交管指令--------------------------------------------*/
                                if (list[i].CMD == 0)
                                {

                                    //寻找该区域的交管是否已经存在，存在则管制该AGV(需要增加一个状态：是否已被管制主，如果都被管制主，则一直通过交管区域。有没有没管制主，则被管制)
                                    List<TrafficInfo> listInTraffic = listTraffic.FindAll(s => s.Area == list[i].Area && s.IP != IP);
                                    
                                    //里面已经存在交管AGV&&该AGV不存在，才能进入；避免多次进入
                                    if (listInTraffic.Count >= 1)
                                    {
                                        //判断在该区域是否已经存在该IP的AGV
                                        TrafficInfo listIsExistsTraffic =listTraffic.Find(s => s.Area == list[i].Area && s.IP == IP);
                                        if (listIsExistsTraffic == null)
                                        {
                                            //发送停止信号
                                            OrderList objOrderList = new OrderList() { CMD = 0x14 };
                                            objAGVCommunicationManager.SendDataByIP(IP, dic, objOrderList);//发送数据
                                        }                                       
                                    }
                                    //先判断该区域是否已存在，避免重复添加
                                    List<TrafficInfo> listHaveTraffic = listTraffic.FindAll(s => s.Area == list[i].Area && s.IP == IP);
                                    if(listHaveTraffic.Count == 0)
                                    {
                                        //lock (objAGV)
                                        //{
                                            listTraffic.Add(new TrafficInfo
                                            {
                                                IP = IP,
                                                AGVName = AGVName,
                                                InTraffic = DateTime.Now,
                                                TrafficStatus = listInTraffic.Count == 0 ? "通行中" : "管制中",
                                                Area = list[i].Area,
                                                LandNum = PreLandNum
                                            }); //新增一个进入交管区域的AGV
                                        //}                                                                          
                                    }
                                }
                                /*--------------------------------------------释放交管指令--------------------------------------------*/
                                else if (list[i].CMD == 1)
                                {
                                   // list[i].OutTraffic = DateTime.Now;
                                    //查找对应区域和交管AGV，并清除该AGV在交管区域的信息（释放交管）
                                    int index = listTraffic.FindIndex(s => s.Area == list[i].Area && s.IP ==IP);
                                    //释放被管制的AGV,不能寻找自己
                                    List<TrafficInfo> listOutTraffic = listTraffic.FindAll(s => s.Area == list[i].Area && s.IP != IP);
                                    //找到有被管制的AGV，如果多个释放最前一台
                                    if (listOutTraffic.Count >= 1 && index != -1)
                                    {
                                        //发送释放信号
                                        Thread.Sleep(200); //延时200ms再发释放，以防AGV不释放
                                        OrderList objOrderList = new OrderList() { CMD = 0x15 };
                                        objAGVCommunicationManager.SendDataByIP(listOutTraffic[0].IP, dic, objOrderList);//发送数据 释放最前面一台
                                        int outIndex = listTraffic.FindIndex(s => s.Area == list[i].Area && s.IP == listOutTraffic[0].IP);
                                        if (outIndex != -1) listTraffic[outIndex].TrafficStatus = "通行中";
                                    }
                                    lock (listTraffic)
                                    {
                                        if (index != -1)
                                            listTraffic.RemoveAt(index); //删除当前运行出交管区域的AGV信息    
                                    }
                                                                   
                                }
                            }
                        }
                        list.Clear();
                    }//end失联
                    //清零
                    PreLandNum = 0;
                    IP = string.Empty;
                    AGVName = string.Empty;
                    PreAGVStatus = string.Empty;
                    OnLineStatus = string.Empty;                 
                }
                listTraffic.Sort(new AreaASC()); //按区域排序
                dgvTrafficView.Invoke(new Action<List<TrafficInfo>>(s =>
                {
                    dgvTrafficView.AutoGenerateColumns = false; dgvTrafficView.DataSource = null; dgvTrafficView.DataSource = s;
                }), listTraffic);
            }
            catch (Exception ex)
            {
                Common.ErrorRecord.WriteErrorLog("交管异常！异常信息："+ ex.Message);
                MessageBox.Show("交管异常！异常信息："+ex.Message);
            }
            
        }
        #endregion
    }

    //交管区域升序排列
    class AreaASC : IComparer<TrafficInfo>
    {
        public int Compare(TrafficInfo x, TrafficInfo y)
        {
            return x.Area - y.Area;
        }
    }
}
